/*
 * Copyright 2020-2022 Yuntu Microelectronics co.,ltd
 * All rights reserved.
 *
 * YUNTU Confidential. This software is owned or controlled by YUNTU and may only be
 * used strictly in accordance with the applicable license terms. By expressly
 * accepting such terms or by downloading, installing, activating and/or otherwise
 * using the software, you are agreeing that you have read, and that you agree to
 * comply with and are bound by, such license terms. If you do not agree to be
 * bound by the applicable license terms, then you may not retain, install,
 * activate or otherwise use the software. The production use license in
 * Section 2.3 is expressly granted for this software.
 */
/**
 * @file tmu_hw_access.c
 */

#include <stddef.h>
#include "tmu_hw_access.h"

/*******************************************************************************
* Definitions
*******************************************************************************/

/*******************************************************************************
 * Code
 ******************************************************************************/

/*FUNCTION**********************************************************************
 *
 * Function Name : TMU_Init
 * Description   : This function restores the TMU module to reset value.
 *
 *END**************************************************************************/
status_t TMU_Init(TMU_Type *const base)
{
    DEV_ASSERT(base != NULL);

    status_t status = STATUS_SUCCESS;

    /* unlock all registers */
    for (int i = 0; i < TMU_MUX_COUNT; i++)
    {
        base->MUX[i] = 0;
    }

    return status;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : TMU_SetTrigSourceForTargetModule
 * Description   : This function configures a TMU link between a source trigger
 * and a target module, if the requested target module is not locked.
 *
 *END**************************************************************************/
void TMU_SetTrigSourceForTargetModule(TMU_Type *const base,
                                      const tmu_trigger_source_t triggerSource,
                                      const tmu_target_module_t targetModule)
{
    DEV_ASSERT(base != NULL);
    DEV_ASSERT(triggerSource < (1 << TMU_MUX_SEL0_WIDTH));
    DEV_ASSERT(targetModule < (TMU_MUX_COUNT * 4));

    uint8_t muxCnt = 0U;
    uint8_t selCnt = 0U;
    uint32_t tmpReg;

    muxCnt = targetModule >> 2;
    selCnt = targetModule & 0x3U;

    /* Read value of entire TMU register in a temp variable */
    tmpReg = base->MUX[muxCnt];
    switch (selCnt)
    {
        case (0x0U):
            tmpReg |= TMU_MUX_SEL0(triggerSource);
            break;
        case (0x1U):
            tmpReg |= TMU_MUX_SEL1(triggerSource);
            break;
        case (0x2U):
            tmpReg |= TMU_MUX_SEL2(triggerSource);
            break;
        case (0x3U):
            tmpReg |= TMU_MUX_SEL3(triggerSource);
            break;
        default:
            break;
    }
    /* Write back the TMU MUX register */
    base->MUX[muxCnt] = tmpReg;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : TMU_GetTrigSourceForTargetModule
 * Description   : This function returns the TMU source trigger linked to
 * a selected target module.
 *
 *END**************************************************************************/
tmu_trigger_source_t TMU_GetTrigSourceForTargetModule(const TMU_Type *const base,
                                                      const tmu_target_module_t targetModule)
{
    DEV_ASSERT(base != NULL);
    DEV_ASSERT(targetModule < (TMU_MUX_COUNT * 4));

    uint8_t muxCnt = 0U;
    uint8_t selCnt = 0U;
    uint8_t trigSource;

    muxCnt = targetModule / 4;
    selCnt = targetModule % 4;

    if (selCnt == 0)
    {
        /* Perform the update operation */
        trigSource = (base->MUX[muxCnt] >> TMU_MUX_SEL0_SHIFT) & TMU_MUX_SEL0_MASK;
    } else if (selCnt == 1)
    {
        /* Perform the update operation */
        trigSource = (base->MUX[muxCnt] >> TMU_MUX_SEL1_SHIFT) & TMU_MUX_SEL1_MASK;
    } else if (selCnt == 2)
    {
        /* Perform the update operation */
        trigSource = (base->MUX[muxCnt] >> TMU_MUX_SEL2_SHIFT) & TMU_MUX_SEL2_MASK;
    } else
    {
        /* Perform the update operation */
        trigSource = (base->MUX[muxCnt] >> TMU_MUX_SEL3_SHIFT) & TMU_MUX_SEL3_MASK;
    }

    return (tmu_trigger_source_t) (trigSource);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : TMU_SetLockForTargetModule
 * Description   : This function sets the Lock bit of the TMU register corresponding
 * to the selected target module.
 *
 *END**************************************************************************/
void TMU_SetLockForTargetModule(TMU_Type *const base,
                                const tmu_target_module_t targetModule)
{
    DEV_ASSERT(base != NULL);
    DEV_ASSERT(targetModule < (TMU_MUX_COUNT * 4));

    uint8_t muxCnt = 0;

    muxCnt = targetModule / 4;

    /* Perform the update operation */
    base->MUX[muxCnt] |= (((uint32_t) 1U) << TMU_MUX_LOCK_SHIFT);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : TMU_GetLockForTargetModule
 * Description   : Get the lock bit status of the TMU register of a target module.
 *
 *END**************************************************************************/
bool TMU_GetLockForTargetModule(const TMU_Type *const base,
                                const tmu_target_module_t targetModule)
{
    DEV_ASSERT(base != NULL);
    DEV_ASSERT(targetModule < (TMU_MUX_COUNT * 4));

    uint8_t muxCnt;
    uint32_t lockVal;
    bool isLock;

    muxCnt = targetModule / 4;

    /* Get the lock bit value */
    lockVal = ((base->MUX[muxCnt] & TMU_MUX_LOCK_MASK) >> TMU_MUX_LOCK_SHIFT);

    isLock = (lockVal == 0U) ? false : true;

    return isLock;
}

/*******************************************************************************
* EOF
*******************************************************************************/
